package com.cantor.provider.handler;

import cn.hutool.core.util.StrUtil;
import com.cantor.core.message.CantorRequestMessage;
import com.cantor.core.pool.CantorExecutorPool;
import com.cantor.provider.invoker.impl.GenericProviderServiceInvoker;
import com.cantor.provider.pojo.ServiceBoat;
import com.cantor.provider.regsitry.ServiceRegistrant;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.ReferenceCountUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;

/**
 * 非阻塞的handler处理器, 请求request请求
 */
@Slf4j
@ChannelHandler.Sharable
public class AsyncCantorRequestMessageHandler extends SimpleChannelInboundHandler<CantorRequestMessage> {

    // 需要一个服务注册者, 从里面拿服务的impl实现实例
    private ServiceRegistrant serviceRegistrant;

    // 构造方法
    public AsyncCantorRequestMessageHandler(ServiceRegistrant serviceRegistrant){
        this.serviceRegistrant = serviceRegistrant;
    }

    // 当有客户端连接来后, 打印客户端的地址
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        log.info("[连接建立] {} ======&====== {} ",ctx.channel().localAddress(),ctx.channel().remoteAddress());
        super.handlerAdded(ctx);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, CantorRequestMessage req) throws Exception {
        log.debug("{} <<< Request <<< {}",ctx.channel().localAddress(),ctx.channel().remoteAddress());
        // 异步执行
        CantorExecutorPool.execute(new Runnable() {
            @Override
            @SneakyThrows
            public void run() {
                // 获取带版本号的服务名
                String interfaceName = req.getInterfaceName();
                if (StrUtil.isNotBlank(req.getServiceVersion())) {
                    interfaceName += ":" + req.getServiceVersion();
                }
                // 获取ServiceBoat
                ServiceBoat serviceBoat = serviceRegistrant.getBoat(interfaceName);

                // 获取impl
                Object impl = serviceBoat.getServiceImpl();

                // 获取具体方法
                Method method = impl.getClass().getDeclaredMethod(req.getMethodName(), req.getParameterTypes());

                // 获取参数值数组
                Object[] paramValues = req.getParameterValue();

                // 获取sequenceId
                long sequenceId = req.getSequenceId();
                log.trace("收到了sequenceId为{}的请求",sequenceId);
                new GenericProviderServiceInvoker(ctx,serviceBoat,impl,method,paramValues,sequenceId).invoke();
                // 释放
                ReferenceCountUtil.release(req);
            }
        });

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
        log.error("处理CantorRequest请求时出错,如果只是客户端连接断开,请忽略");
        ctx.close();
    }

}
